package com.zfei.gfb.util;

import com.google.gson.*;
import com.zfei.gfb.util.gson.GsonBox;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;

/**
 * @author fgh
 */
public class Gsons {

    // -------------------------
    // JSON ELEMENT OPERATIONS
    // -------------------------

    private static final JsonParser PARSER = new JsonParser();

    public static JsonParser getParser() {
        return PARSER;
    }

    public static String getString(JsonObject jo, String key) {
        return getString(jo, key, null);
    }

    public static String getString(JsonObject jo, String key, String dv) {
        if (jo.has(key) && !jo.get(key).isJsonNull()) {
            return jo.get(key).getAsString();
        } else {
            return dv;
        }
    }

    public static Long getLong(JsonObject jo, String key) {
        return getLong(jo, key, null);
    }

    public static Long getLong(JsonObject jo, String key, Long dv) {
        if (jo.has(key) && !jo.get(key).isJsonNull()) {
            return jo.get(key).getAsLong();
        } else {
            return dv;
        }
    }

    public static Integer getInt(JsonObject jo, String key) {
        return getInt(jo, key, null);
    }

    public static Integer getInt(JsonObject jo, String key, Integer dv) {
        if (jo.has(key) && !jo.get(key).isJsonNull()) {
            return jo.get(key).getAsInt();
        } else {
            return dv;
        }
    }

    public static Byte getByte(JsonObject jo, String key) {
        return getByte(jo, key, null);
    }

    public static Byte getByte(JsonObject jo, String key, Byte dv) {
        if (jo.has(key) && !jo.get(key).isJsonNull()) {
            return jo.get(key).getAsByte();
        } else {
            return dv;
        }
    }

    public static Double getDouble(JsonObject jo, String key) {
        return getDouble(jo, key, null);
    }

    public static Double getDouble(JsonObject jo, String key, Double dv) {
        if (jo.has(key) && !jo.get(key).isJsonNull()) {
            return jo.get(key).getAsDouble();
        } else {
            return dv;
        }
    }

    public static Boolean getBoolean(JsonObject jo, String key) {
        return getBoolean(jo, key, null);
    }

    public static Boolean getBoolean(JsonObject jo, String key, Boolean dv) {
        if (jo.has(key) && !jo.get(key).isJsonNull()) {
            return jo.get(key).getAsBoolean();
        } else {
            return dv;
        }
    }

    public static JsonObject getJsonObject(JsonObject jo, String key) {
        JsonElement je = jo.get(key);
        if (je != null && je.isJsonObject()) {
            return je.getAsJsonObject();
        }
        return new JsonObject();
    }

    public static JsonArray getJsonArray(JsonObject jo, String key) {
        JsonElement je = jo.get(key);
        if (je != null && je.isJsonArray()) {
            return je.getAsJsonArray();
        }
        return new JsonArray();
    }

    public static JsonElement parseJsonElement(String str) {
        return str == null ? null : getParser().parse(str);
    }

    public static JsonObject parseJsonObject(String src) {
        return StringUtils.isBlank(src) ? new JsonObject() : getParser().parse(src).getAsJsonObject();
    }

    public static JsonArray parseJsonArray(String src) {
        return StringUtils.isBlank(src) ? new JsonArray() : getParser().parse(src).getAsJsonArray();
    }

    public static JsonObject copyJsonObject(JsonObject src) {
        JsonObject ret = new JsonObject();
        Set<Map.Entry<String, JsonElement>> entries = src.entrySet();
        for (Map.Entry<String, JsonElement> entry : entries) {
            ret.add(entry.getKey(), entry.getValue());
        }
        return ret;
    }

    public static void copyJsonObject(JsonObject src, JsonObject ret) {
        Set<Map.Entry<String, JsonElement>> entries = src.entrySet();
        for (Map.Entry<String, JsonElement> entry : entries) {
            if (entry.getValue() != null && !entry.getValue().isJsonNull()) {
                ret.add(entry.getKey(), entry.getValue());
            } else {
                ret.remove(entry.getKey());
            }
        }
    }

    public static void cutJsonObject(JsonObject src, JsonObject ret) {
        Set<Map.Entry<String, JsonElement>> entries = src.entrySet();
        for (Map.Entry<String, JsonElement> entry : entries) {
            ret.remove(entry.getKey());
        }
    }

    public static JsonObject mergeJsonObject(JsonObject... jos) {
        JsonObject ret = new JsonObject();
        for (JsonObject jo : jos) {
            Set<Map.Entry<String, JsonElement>> entries = jo.entrySet();
            for (Map.Entry<String, JsonElement> entry : entries) {
                ret.add(entry.getKey(), entry.getValue());
            }
        }
        return ret;
    }

    // -------------------------
    // GSON BASE DELEGATION
    // -------------------------

    public static Gson get() {
        return GsonBox.BASE;
    }

    public static <T> T fromJson(String str, Class<T> clazz) {
        return get().fromJson(str, clazz);
    }

    public static <T> T fromJson(JsonElement json, Class<T> clazz) {
        return get().fromJson(json, clazz);
    }

    public static <T> T fromJson(String str, Type type) {
        return get().fromJson(str, type);
    }

    public static <T> T fromJson(JsonElement json, Type type) {
        return get().fromJson(json, type);
    }

    public static String toJson(Object obj) {
        return get().toJson(obj);
    }

    public static JsonElement toJsonTree(Object obj) {
        return get().toJsonTree(obj);
    }
}
